/**
 * Copyright (C) 2010 DustedPixels.com
 */
package com.dustedpixels.cirt.awt;

import java.awt.Canvas;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;

import com.google.common.base.Preconditions;

/**
 * ZxCanvas
 *
 * @author Michal Pociecha-Los (micapolos@gmail.com)
 */
public final class VideoComponents {

  /**
   * Creates and returns new {@link Component}, which will display the content
   * of given video data.
   * 
   * @param graphicsConfiguration
   * @param screenData
   * @param width
   * @param height
   * @param redPalette
   * @param greenPalette
   * @param bluePalette
   * @return
   */
  public static Component newHeavyweightComponent(
      final GraphicsConfiguration graphicsConfiguration,
      final BufferedImage videoImage) {
    Preconditions.checkNotNull(graphicsConfiguration);
    Preconditions.checkNotNull(videoImage);

    // Create VolatileImage, which will be used for hardware accelerated 
    // rendering
    final VolatileImage volatileImage = 
        graphicsConfiguration.createCompatibleVolatileImage(
            videoImage.getWidth(), 
            videoImage.getHeight());
    
    // Create a Graphics2D object which will be used to copy screen bytes into
    // the volatile image
    final Graphics2D volatileImageGraphics = volatileImage.createGraphics();
    
    // Finally, create a canvas component, which will render video content. 
    Canvas canvas = new Canvas(graphicsConfiguration) {
      private static final long serialVersionUID = -7380766250922512404L;

      @Override
      public void paint(Graphics g) {
        Graphics2D graphics2D = (Graphics2D) g;

        synchronized (videoImage) {
          // Draw into volatile image
          // TODO(micapolos): What about validating and reconstructing 
          // VolativeImage?
          volatileImageGraphics.drawImage(videoImage, 0, 0, null);
        }
        
        // Draw volatile image into this canvas.
        graphics2D.drawImage(volatileImage, 0, 0, getWidth(), getHeight(), null);
      }

      @Override
      public void update(Graphics g) {
        paint(g);
      }
    };
    
    return canvas;
  }

  /**
   * Creates and returns new {@link Component}, which will display the content
   * of given video data.
   * 
   * @param graphicsConfiguration
   * @param screenData
   * @param width
   * @param height
   * @param redPalette
   * @param greenPalette
   * @param bluePalette
   * @return
   */
  public static Component newLightweightComponent(
      final GraphicsConfiguration graphicsConfiguration,
      final BufferedImage videoImage) {
    Preconditions.checkNotNull(graphicsConfiguration);
    Preconditions.checkNotNull(videoImage);

    // Finally, create a canvas component, which will render video content. 
    Component component = new Canvas(graphicsConfiguration) {
      private static final long serialVersionUID = -7380766250922512404L;

      @Override
      public void paint(Graphics g) {
        synchronized (videoImage) {
          g.drawImage(videoImage, 0, 0, getWidth(), getHeight(), null);
        }
      }

      @Override
      public void update(Graphics g) {
        paint(g);
      }
    };
    
    return component;
  }
}
